<?php
require_once(dirname(__FILE__)."/cluster_form_parameter.class.php"); 
class client {
	private $session;
	private $request;
	public $client;
	private $characteristics_checked = array();
	/**
	 * Constructor
	 *
	 */
	public  function __construct($form) {
		$this->characteristics_checked = array();
		$this->client = new SoapClient("http://localhost:1755/Services/Service.asmx?WSDL", array("classmap"=>global_config::get_instance()->classmap/*, " connection_timeout"=>600*/));
		$this->send_request($form);
	}



	/**
	 * Set request to the server
	 *
	 *
	 */
	private function send_request($form) {
		//var_dump($form['exp']);
		if (!empty($form['exp'])) {
			if ($form['exp']=='create_alphabet'){$this->build_simple_request($form,'Create Alphabet by Block');}
			if ($form['exp']=='calculate'){$this->build_simple_request($form,'Calculate');}
			if ($form['exp']=='markov') {$this->build_markov_experiment_request($form);}
			if ($form['exp']=='analysis') {$this->send_analysis_experiment_request($form);}
		}
	}

	/**
	 * Build create alphabet request
	 *
	 *
	 */
	private function build_simple_request($form,$experiment_action)
	{

		if (!empty($_SESSION['sequence_count'])) {
			$counter = 1;
			while ($counter<=$_SESSION['sequence_count']) {
				$request_to_server=$this->add_sequence_to_request($form, $counter,$experiment_action);
				if ($experiment_action == 'Calculate') {$this->save_server_answer_calculate($form,$request_to_server,$counter);}
				if ($experiment_action == 'Create Alphabet by Block') {$this->save_server_answer_create_alphabet($form,$request_to_server,$counter);}
				$counter=$counter+1;
			}
		}
	}

	/**
	 * sdd sequence to request
	 *
	 * @return request
	 */
	private function add_sequence_to_request($form, $counter,$key) {
		$sequen = new sequence_composition();
		$sequence_list = new sequence_composition();
		$criteria = new query_criteria();
		$criteria->add_criterion($sequen->sequence->sequence_id, criterion_type::$equal, $form['sequence_count'.$counter]);
		$sequence_list = db_adapter::get_instance()->get_composite_list($sequen,$criteria);
		$sequence = $sequence_list->get_next(false,true);
		$filetype = new soap_file_type();
		$filetype->Name = $sequence->file_type->file_type_name->get_value();
		$filetype->MIME = $sequence->file_type->file_type_mime->get_value();
		$filetype->Size = $sequence->file_type->file_type_size->get_value();
		$filetype->HashCode = 1054010489;

		$file = new soap_file();
		$file->FileType = $filetype;
		$file->Data = $sequence->files->file_file->get_value();
		$req = new soap_request_files();

		$action = new soap_action_type();
		$action->Name = $key;
		$action->MIME = $key;
		$action->HashCode = 1983783733;
		$action->LinkUp = 'Start';
		if ($key = 'Create Alphabet by Block') {
			$action->BlockSize = $form["length"];}
			if ($key = 'Calculate'){
				$action->BlockSize = $form["length_for_calculate"];}
				$req->Action = $action;
				$req->Files = $file;
				return $req;

	}


	/**
	 * Save server ansver to db
	 *
	 *
	 */
	private function save_server_answer_calculate($form,$req,$counter) 
	{
		//TODO: проверка на ошибки

		$result = $this->client->Calculate(array("request"=>$req));
		$result->CalculateResult->Chain->sequence_id =  $form['sequence_count'.$counter];
		$result->CalculateResult->Chain->save_to_db('CalculateResult');
		var_dump(12312413245);
	}

	/**
	 * Save server ansver to db
	 *
	 *
	 */
	private function save_server_answer_create_alphabet($form,$req,$counter) {
		//TODO: проверка на ошибки
		$result = $this->client->CreateAlphabet(array("request"=>$req));
		$result->CreateAlphabetResult->Alphabet->save_to_db('CreateAlphabetResult');
		var_dump(12312413245);
	}

	private function _validate_markov_iformation($form) {
		//TODO: Сделать ограничения на значения
		$errors = error_logger::get_instance();
		if (empty($form['markov_chain_rang'])) {
			$errors->add("Markov Chain Rang can not be empty");
		}

		if (empty($form['generate_chains_count'])) {
			$errors->add("Count of generated chains can not be empty");
		}

		if (empty($form['length_of_chains'])) {
			$errors->add("Length of chains can not be empty");
		}
		if (empty($form['pre_changes'])) {
			$errors->add("Please choose prechanges");
		}
		if (empty($form['pre_changes'])) {
			$errors->add("Please choose prechanges");
		}
		if (empty($form['pre_changes'])) {
			$errors->add("Please choose generator type");
		}

	}

	/**
	 * Build make markov experiment request
	 *
	 * @return request
	 */
	private function build_markov_experiment_request($form) {

		$response = new xajaxResponse();
		$response->clear("errors", "innerHTML");
		$errors = error_logger::get_instance();

		/*	$this->_validate_markov_iformation($form);

		if ($errors->count()) {
		$tpl = new simple_page($this->module, $this->action);
		$tpl->assign_by_ref("error_logger", $errors);
		$response->assign("errors", "innerHTML", $tpl->fetch("errors_wrapper.tpl"));
		return $response;
		}*/
		if (!empty($_SESSION['chain_count'])) {
			$counter = 1;
			while ($counter<=$_SESSION['chain_count']) {
				$request_to_server=$this->add_chain_object_to_request($form, $counter);
				$this->save_server_markov_answer($form,$request_to_server,$counter);
				$counter++;
			}
		}
		return $request_to_server;
	}

	/**
	 * sdd chain object to request
	 *
	 * @return request
	 */
	private function add_chain_object_to_request($form, $counter) {
		$markov_chain = new soap_request_markov_chains();
		$markov_chain->GenerateChainsCount = $form["generate_chains_count"];
		$markov_chain->Generator = $form["generator"];
		$markov_chain->Method = $form["method"];
		$markov_chain->MarkovChainRang = $form["markov_chain_rang"];
		$markov_chain->PreChanges = $form["pre_changes"];
		$markov_chain->Length = $form["length_of_chains"];
		$markov_chain->Chain->load_from_db($form['chain_count'.$counter]);
		return $markov_chain;
	}

	/**
	 * Save markov server ansver to db
	 *
	 *
	 */
	private function save_server_markov_answer($form,$req,$counter) {
		//TODO: проверка на ошибки
		unset($form["add"]);
		unset($form["back"]);
		unset($form["go"]);
		unset($form["length"]);
		unset($form["step"]);
		unset($form["Matrix"]);
		unset($form["alphabets"]);
		unset($form["methods"]);
		$experiment_id = $this->save_experiment($form,'MarkovChain');

		$result = $this->client->MarkovChain(array("request"=>$req));
		$temp = $result->MarkovChainResult->Chains->as_array() ;
		foreach ($temp as &$item) {
			$item->parent_id = $form['chain_count'.$counter];
			$item->experiment_id = $experiment_id;
			$item->save_to_db();
		}
		var_dump(123124132455767867);
	}

	/**
	 * Save experiment to db
	 *
	 *
	 */
	private function save_experiment($form,$experiment_name) {
		$experiment = new experiment();
		$dba = db_adapter::get_instance();
		$experiment->experiment_name->set_value($form["exp"]);
		$dba->save_unique($experiment);
		unset($form["exp"]);
		foreach ($form as $key => $value) {
			$parametr_type = new parametr_type();
			$parametr_type->parametr_type_name->set_value($key);
			db_adapter::get_instance()->save_unique($parametr_type);
			$parametr_value = new parametr_value();
			$parametr_value->parametr_value->set_value($value);
			$parametr_value->parametr_type_id->set_value($parametr_type->parametr_type_id->get_value());
			$parametr_value->experiment_id->set_value($experiment->experiment_id->get_value());
			db_adapter::get_instance()->save_unique($parametr_value);
		}
		return $experiment->experiment_id->get_value();
	}


	private function _validate_analysis_iformation($form) {
		//TODO: Сделать ограничения на значения

		$errors = error_logger::get_instance();
		if (empty($form['cluster_count'])) {
			$errors->add("Cluster count can not be empty");
		}
	}

	/**
	 * Send analysis request
	 *
	 * @return request
	 */
	private function send_analysis_experiment_request($form) {
		$request_to_server=$this->build_analysis_experiment_request($form, $counter);
		$this->save_server_analysis_answer($form,$request_to_server,$counter);
		return $request_to_server;
	}


	/**
	 * Build make analysis request
	 *
	 * @return request
	 */
	private function build_analysis_experiment_request($form) {

	
		if (!empty($_SESSION['chain_count'])) {
			$counter = 1;
			$type_description = array();
			$table_object = new soap_data_table();
			$table_object->Objects = new soap_array_of_soap_data_object();			
			
			
			while ($counter<=$_SESSION['chain_count']) {
				$chain = new soap_chain();
				$chain->load_from_db($form['chain_count'.$counter]);

				$characteristic = new chain_characteristic_type();
				$dba = db_adapter::get_instance();
				$characteristic_list = $dba->get_list($characteristic);
				$object = new soap_data_object();
				$object->id = $form['chain_count'.$counter];
				$object->vault = new soap_array_of_data_characteristic();

				while($characteristic = $characteristic_list->get_next())
				{
					$type_description[$characteristic->chain_characteristic_type_name->get_value()] = $characteristic->chain_characteristic_type_description->get_value().'.'.$characteristic->chain_characteristic_type_id->get_value();
				}

				$values = (array)$chain->Characteristics;
				$values = array_values($values);
				$values = is_array($values[0])? current($values) : $values;

				foreach ($values as $characteristic)
				{
					$type_name = $characteristic->Type;
					$characteristic_name = $type_description[$type_name];
					if ($form["chain.".$characteristic_name]==true)
					{
						$id_name = substr($characteristic_name, strpos($characteristic_name, '.')+1);	
						$this->characteristics_checked[$id_name] = $characteristic_name;
						$temp = new soap_data_characteristic();
						$temp->Key = $characteristic_name;
						$temp->Value = $characteristic->$form["chain_value_type_select"];
						$object->vault->add($temp);
					}
				}

				foreach ($type_description as $long_name => $short_name) {
					if ($form["uniform_chain.".$short_name]==true){
						$alphabet_id_value = array();
						$values = (array)$chain->UniformChains;
						$values = array_values($values);
						$values = is_array($values[0])? current($values) : $values;

						foreach ($values as $uchain)
						{
							$values = (array)$uchain->Characteristics;
							$values = array_values($values);
							$values = is_array($values[0])? current($values) : $values;

							foreach ($values as $characteristic)
							{
								if ($long_name == $characteristic->Type)
								{
									$alphabet_id_value[$uchain->Alphabet->Alphabet_id] = $characteristic->$form["chain_value_type_select"];
								}
							}
						}

						if ($form["uniform_chain.".$short_name.".select"]=="Value")
						{

							asort($alphabet_id_value);
							$temp = array();
							$i = 0;
							foreach ($alphabet_id_value as $value) {
								$temp[$short_name.$i] = $value;
							}
							$alphabet_id_value = $temp;


						}elseif($form["uniform_chain.".$short_name.".select"]=="Name")
						{
							ksort($alphabet_id_value);
						}

						foreach ($alphabet_id_value as $name => $value)
						{
							$temp = new soap_data_characteristic();
							$temp->Key = $short_name.$name;
							$temp->Value = $value;
							$object->vault->add($temp);
						}
					}
				}
				$counter=$counter+1;
				$table_object->Objects->add($object);
			}

			$req = new soap_request_clusterization();
			$req->DataTable = $table_object;
			$req->Method= $form["method_select"];
			$req->ClusterCount = $form["cluster_count"];
		}
		return $req;
	}

	/**
	 * Save analysys server ansver to db
	 *
	 *
	 */
	private function save_server_analysis_answer($form,$req,$counter) {
		//TODO: проверка на ошибки
		unset($form["add"]);
		unset($form["back"]);
		unset($form["go"]);
		unset($form["length"]);
		unset($form["step"]);
		unset($form["Matrix"]);
		unset($form["alphabets"]);

		$form_object = new cluster_form();
		$form_object->create($form);

		$experiment_id = $this->save_experiment($form,'Clusterization');
		$result = $this->client->KRAB(array("request"=>$req));

	
		$counter = 1;
		$clusrterisation_variants = array();
		$dba = db_adapter::get_instance();
		foreach ($form_object->chains as $chain_id) {
			$clusterisation_chain = new clusterisation_chain();
			$criteria = new query_criteria();
			$criteria->add_criterion($clusterisation_chain->chain_id,criterion_type::$equal,$chain_id);
				
			$clusrterisation_list = $dba->get_list($clusterisation_chain,$criteria);
			$array_cross = array();
			while ($item = $clusrterisation_list->get_next()){
				$clusrterisation_variants[] = $item->clusterisation_id->get_value();
			}
			$array_cross = !empty($array_cross)? array_intersect($array_cross, $clusrterisation_variants) : $array_cross = $clusrterisation_variants;	
		}
	
		$clusterisation_array = array();
		foreach ($array_cross as $item){
			$clusterisation_chain = new clusterisation_chain();
			$criteria = new query_criteria();
			$criteria->add_criterion($clusterisation_chain->clusterisation_id,criterion_type::$equal,$item);
			$clusrterisation_variants = $dba->get_list($clusterisation_chain,$criteria);
			
			if ($clusrterisation_variants->count()==count($form_object->chains)){
				$clusterisation_array[]=$item;
			}
		}
		$array_cross = $clusterisation_array;
		
		$clusterisation_array = array();
		foreach ($array_cross as $item){
			$clusterisation= new clusterisation();
			$criteria = new query_criteria();
			$criteria->add_criterion($clusterisation->clusterisation_id,criterion_type::$equal,$item);
			$dba->load($clusterisation,$criteria);
			
			if ($clusterisation->linkup->get_value()==$form_object->link_up){
				$clusterisation_array[]=$item;
			}
		}
		
		$array_cross = $clusterisation_array;
		$clusterisation_array = array();
		foreach ($array_cross as $item){
			$clusterisation_parametrs = new clusterisation_parametrs();
			$criteria = new query_criteria();
			$criteria->add_criterion($clusterisation_chain->clusterisation_id,criterion_type::$equal,$item);
			$clusterisation_parametrs_list = $dba->get_list($clusterisation_chain,$criteria);
			
			if ($clusterisation_parametrs_list->count()==count($form_object->characteristics)){
				$find = true;
				while ($list_item = $clusterisation_parametrs_list->get_next()){
					$characteristic =$form_object->characteristics[$list_item->characteristic_type_id->get_value()]; 
					if(empty($characteristic) || ($characteristic->sort!=$list_item->sort->get_value()))
					{
						$find = false;
					}
				}
				if ($find)
				{
					$clusterisation_array[] = $item;
				}
			}
		}
		
		$array_cross = $clusterisation_array;
		
		$clusterisation_id = 0; 
		if (!empty($array_cross))
		{
			$clusterisation_id = $array_cross[0]; 
		}else 
		{
			$clusterisation_id = $form_object->save_new_clusterisation();
		}
		
		var_dump($result);
			
/*		foreach ($result->KRABResult->Variant->Variants->as_array() as $item) 
		{

			$item->clusterisation_id = $clusterisation_id;
			$item->save_to_db();
			
		}
*/		var_dump(123124132455767867);
	}


}
?>
